home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.2 Applications 1996 May / SGI IRIX 6.2 Applications 1996 May.iso / dist / impr_dev.idb / usr / impressario / src / scan / template_driver / scan.c.z / scan.c
C/C++ Source or Header  |  1996-05-06  |  21KB  |  667 lines

  1. /*
  2.  * scan.c
  3.  *
  4.  *     Scanner specific module of a scanner driver.  This is a
  5.  *     template for developing a scanner driver for an SGI system;
  6.  *     add code that communicates with your scanner in the
  7.  *     appropriate places below, and link with main.o and libscan.a
  8.  *     to build a scanner driver.
  9.  *
  10.  * Copyright 1992, Silicon Graphics, Inc.
  11.  * All Rights Reserved.
  12.  *
  13.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  14.  * the contents of this file may not be disclosed to third parties, copied or
  15.  * duplicated in any form, in whole or in part, without the prior written
  16.  * permission of Silicon Graphics, Inc.
  17.  *
  18.  * RESTRICTED RIGHTS LEGEND:
  19.  * Use, duplication or disclosure by the Government is subject to restrictions
  20.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  21.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  22.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  23.  * rights reserved under the Copyright Laws of the United States.
  24.  */
  25.  
  26. #ident "$Revision: 1.17 $"
  27.  
  28. #include <sys/types.h>
  29. #include <sys/prctl.h>
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <dslib.h>
  35. #include <fcntl.h>
  36. #include <invent.h>
  37. #include <scanner.h>
  38. #include <scandrv.h>
  39.  
  40. #include "scan.h"
  41. #include "main.h"
  42.  
  43. /*
  44.  * struct for the data from a SCSI inquiry command
  45.  */
  46. typedef    struct
  47. {
  48.     unchar    pqt:3;       /* peripheral qual type */
  49.     unchar    pdt:5;       /* peripheral device type */
  50.     unchar    rmb:1,       /* removable media bit */
  51.         dtq:7;       /* device type qualifier */
  52.     unchar    iso:2,       /* ISO version */
  53.         ecma:3,       /* ECMA version */
  54.         ansi:3;       /* ANSI version */
  55.     unchar    aenc:1,       /* async event notification supported */
  56.         trmiop:1,  /* device supports 'terminate io process msg */
  57.         res0:2,       /* reserved */
  58.         respfmt:3; /* SCSI 1, CCS, SCSI 2 inq data format */
  59.     unchar    ailen;       /* additional inquiry length */    
  60.     unchar    res1;       /* reserved */
  61.     unchar    res2;       /* reserved */
  62.     unchar    reladr:1,  /* supports relative addressing (linked cmds) */
  63.         wide32:1,  /* supports 32 bit wide SCSI bus */
  64.         wide16:1,  /* supports 16 bit wide SCSI bus */
  65.         synch:1,   /* supports synch mode */
  66.         link:1,       /* supports linked commands */
  67.         res3:1,       /* reserved */
  68.         cmdq:1,       /* supports cmd queuing */
  69.         softre:1;  /* supports soft reset */
  70.     unchar    vid[8];       /* vendor ID */
  71.     unchar    pid[16];   /* product ID */
  72.     unchar    prl[4];       /* product revision level*/
  73.     unchar    vendsp[20];/* vendor specific; typically firmware info */
  74.     unchar    res4[40];  /* reserved for scsi 3, etc. */
  75.     /* more vendor specific information may follow */
  76. } INQDATA;
  77.  
  78. /*
  79.  *  SCANINFO *
  80.  *  OpenScanner(char *dev)
  81.  *
  82.  *  Description:
  83.  *      Get a SCANINFO structure for the scanner connected to dev.
  84.  *      This opens the device and does an inquiry to find out what
  85.  *      kind of scanner is attached.  If it's one we know about, we
  86.  *      allocate a SCANINFO structure, fill it in, and return it.
  87.  *
  88.  *  Parameters:
  89.  *      dev  device for the scanner
  90.  *
  91.  *  Returns:
  92.  *      pointer to a SCANATTRIB if successful, NULL with drverr set if
  93.  *      error.
  94.  */
  95.  
  96. /*ARGSUSED*/
  97. SCANINFO *
  98. OpenScanner(char *dev)
  99. {
  100.     static SCANINFO scan;
  101.  
  102.     /*
  103.      * VERY IMPORTANT NOTE:
  104.      * 
  105.      * If you are writing a driver for a SCSI scanner, and you are
  106.      * using libds, make sure that you pass the O_EXCL flag defined in
  107.      * /usr/include/fcntl.h to dsopen:
  108.      * 
  109.      *     dsreq_t *dsp = dsopen(dev, O_RDONLY | O_EXCL);
  110.      * 
  111.      * If you pass the O_EXCL flag, the open will fail with errno set
  112.      * to EBUSY if dev is the /dev/scsi device of a mounted disk;
  113.      * otherwise, the open can succeed and you could really screw up
  114.      * the disk!
  115.      * 
  116.      * In addition, it is recommended that before issuing any other
  117.      * SCSI commands you perform an inquiry command, and verify that
  118.      * the device is a scanner by examining the Device Type code of
  119.      * the inquiry buffer (this field should be set to 6.  You can use
  120.      * the INV_SCANNER #define from /usr/include/invent.h).  It is
  121.      * also recommended that you examine the vendor and product
  122.      * identifiers to make sure the device is a scanner of the type
  123.      * for which this driver is being written.
  124.      */
  125.     
  126.     /*
  127.      * Set the fields of scan to meaningful values as follows:
  128.      *
  129.      * scan.metric - Use this to indicate whether measurements are
  130.      *     in inches or centimeters.  This applies to all the
  131.      *     fields of scan that we set that are measurements, and
  132.      *     when SetupScan is called (see below), this will be the
  133.      *     unit of measure for the scanning window and the
  134.      *     scanning resolution.
  135.      *
  136.      * scan.pagex, scan.pagey, scan.pagewidth, scan.pageheight - the
  137.      *     size of the scannable area supported by the scanner.  Set
  138.      *     scan.pagex and pagey to the minimum horizontal and vertical
  139.      *     values for a scanning window (almost always 0 and 0), and
  140.      *     scan.pagewidth and scan.pageheight to the width and height
  141.      *     of the scanning area.  The right edge of a scanning window
  142.      *     will not exceed scan.pagex + scan.pagewidth, and the bottom
  143.      *     edge will not exceed scan.pagey + scan.pageheight.
  144.      *
  145.      * scan.minxres, scan.maxxres, scan.minyres, scan.maxyres - Set
  146.      *     these to the minimum and maximum supported resolutions in
  147.      *     the horizontal and vertical directions.
  148.      *
  149.      * scan.xres, scan.yres - set these to arrays of floating point
  150.      *     numbers representing the discrete resolutions supported in
  151.      *     the horizontal and vertical directions respectively.  If
  152.      *     the scanner we're supports arbitrary resolutions within the
  153.      *     ranges specified with scan.minxres, scan.maxxres,
  154.      *     scan.minyres, and scan.maxyres, we don't set these and we
  155.      *     set scan.nres to 0 (see below).
  156.      *
  157.      * scan.nres - Set this to the number of elements in scan.xres and
  158.      *     scan.yres (the arrays must have equal numbers of elements).
  159.      *     Set scan.nres to 0 to indicate that any resolution is
  160.      *     supported within the bounds indicated (see above).
  161.      *
  162.      * scan.types - Set this to point to an array of SCDATATYPE
  163.      *     structures, one for each of the data types this scanner
  164.      *     supports.  See the Scanner API Specification for type
  165.      *     conventions for well-behaved scanner drivers.
  166.      *
  167.      * scan.ntypes - The number of types in the scan.types array.
  168.      *
  169.      * scan.options - An array of pointers to functions to implement
  170.      *     scanner specific options.  Each function has the format of
  171.      *     the callback functions in main.c.  Command values start at
  172.      *     SCN_SCANSPECIFIC (#defined in <scanipc.h>.  The 0th element
  173.      *     of scan.types will be called when the command
  174.      *     (SCN_SCANSPECIFIC + 0) is received by the library, the 1st
  175.      *     element is called when the command (SCN_SCANSPECIFIC + 1)
  176.      *     is received, and so on.  The interpretation of the SCARGS
  177.      *     and SCRES parameters should be agreed upon by this module
  178.      *     and the scanner specific option program that made the call.
  179.      *
  180.      * scan.noptions - The number of scanner specific options in
  181.      *     scan.options
  182.      *
  183.      * scan.priv - This is a private member for use of this module.
  184.      *     Set it to point to anything you want; this is useful for
  185.      *     avoiding the use of global variables within this module.
  186.      */
  187.  
  188.     return &scan;
  189. }
  190.  
  191. /*
  192.  *  int
  193.  *  SetupScan(SCANPARAMS *params)
  194.  *
  195.  *  Description:
  196.  *      Get ready to perform a scan.  params is a value result
  197.  *      parameter; it has fields that describe the scanning parameters
  198.  *      desired by the scanning application, and fields that this
  199.  *      function is responsible for setting.
  200.  *
  201.  *  Parameters:
  202.  *      params  scanning parameters (in/out)
  203.  *
  204.  *  Returns:
  205.  *      0 if successful, -1 with drverr set if error
  206.  */
  207.  
  208. /*ARGSUSED*/
  209. int
  210. SetupScan(SCANPARAMS *params)
  211. {
  212.     /*
  213.      * The input parameters to use to set up the scan are:
  214.      *     params->s - The SCANINFO struct we returned from OpenScanner
  215.      *
  216.      *     params->xres, params->yres - scanning resolution.
  217.      *         These will be resolutions that we returned via the
  218.      *         SCANINFO struct from OpenScanner.
  219.      *
  220.      *     params->x, params->y, params->width, params->height - The
  221.      *         scanning window.  This will be inside the window
  222.      *         defined by the pagex, pagey, pagewidth, and pageheight
  223.      *         fields of the SCANINFO struct we returned from OpenScanner.
  224.      *
  225.      *     params->type - The data type to scan.  This will be one of
  226.      *         the types we returned via the SCANINFO struct from
  227.      *         OpenScanner.
  228.      *
  229.      *     params->preview - 1 if this is a preview, 0 if this is a
  230.      *         final scan.
  231.      *
  232.      *     params->maxmem - The maximum amount of memory to use for
  233.      *         each chunk we scan; params->xbytes * params->readlines
  234.      *         (see output parameters, below) should not exceed this
  235.      *         value.  This is advisory, not enforced; if for some
  236.      *         reason it is necessary to set readlines such that
  237.      *         maxmem is exceeded, the main module of the driver will
  238.      *         honor params->readlines rather than adhering to
  239.      *         params->maxmem.
  240.      *
  241.      * Output parameters that we must set before returning 0:
  242.      *     params->xpixels - The number of pixels in a scan line
  243.      *
  244.      *     params->xbytes - The number of bytes in a scan line
  245.      *
  246.      *     params->ylines - The number of scan lines in the scan
  247.      *
  248.      *     params->readlines - The number of scan lines to read at a
  249.      *         time.  This parameter becomes significant in DoScan(),
  250.      *         below.  In DoScan(), we get buffers from a scan queue
  251.      *         into which we're supposed to put the scan data; each
  252.      *         buffer will be big enough to hold params->readlines
  253.      *         lines of data.
  254.      *
  255.      *     params->convert - Function to convert scan data to
  256.      *         params->type.  The scanner may not directly support the
  257.      *         four basic types, but we may be able to convert to one
  258.      *         of them; for example, some scanners return color data
  259.      *         in a banded format, where the red, blue, and green
  260.      *         values for each scan line are together.  In this case,
  261.      *         we would set params->convert to SCBandRGB8ToPixelRGB8;
  262.      *         this is the function in the scan library for doing the
  263.      *         conversion we want.
  264.      *
  265.      *         If the scanner returns data in precisely the format
  266.      *         we're returning to the scanning application, no
  267.      *         conversion is necessary, and we can leave
  268.      *         params->convert alone (it will have been initialized to
  269.      *         NULL to indicate that no conversion is necessary).
  270.      *
  271.      * Other parameters
  272.      *     scanq, sfreeq - These are the queues for scan buffers, used
  273.      *         in DoScan below.  They are not significant in ScanSetup
  274.      *         and should be ignored here.
  275.      */
  276.     drverr = SCEDEV; /* Generic "device error" error code; see */
  277.              /* <scanner.h> for more specific error codes */
  278.     return -1;
  279. }
  280.  
  281. /*
  282.  *  int
  283.  *  ScanReset(SCANINFO *scan)
  284.  *
  285.  *  Description:
  286.  *      Reset the scanner to its ready state.  This is called after a
  287.  *      scan has been aborted.
  288.  *
  289.  *  Parameters:
  290.  *      scan  Describes the scanner to reset
  291.  *
  292.  *  Returns:
  293.  *      0 if successful, -1 with drverr set if error
  294.  */
  295.  
  296. /*ARGSUSED*/
  297. int
  298. ScanReset(SCANINFO *scan)
  299. {
  300.     drverr = SCEDEV; /* Generic "device error" error code; see */
  301.              /* <scanner.h> for more specific error codes */
  302.     return -1;
  303. }
  304.  
  305. /*
  306.  *  void
  307.  *  DoScan(SCANPARAMS *params)
  308.  *
  309.  *  Description:
  310.  *      Perform a scan.  We read the data from the scanner and put it on the
  311.  *      scan queue so that the image processing process can get it.  This
  312.  *      function exits when it's done; it's called via sproc(2).
  313.  *
  314.  *      Note: calls to SCEnqueue and SCDequeue may not return; that
  315.  *      is, these functions will call exit if our parent process sets
  316.  *      certain flags.  Be careful that an exit from within SCEnqueue
  317.  *      or SCDequeue will not strand any memory or leave the address
  318.  *      space corrupted in any way.
  319.  *
  320.  *  Parameters:
  321.  *      params  parameters for the scan
  322.  */
  323.  
  324. void
  325. DoScan(SCANPARAMS *params)
  326. {
  327.     void *buf;
  328.     int toread, curline;
  329.  
  330.     (void)prctl(PR_TERMCHILD);
  331.  
  332.     for (curline = 0; curline < params->ylines;
  333.      curline += params->readlines) {
  334.     toread = MIN(params->readlines,
  335.              params->ylines - curline);
  336.  
  337.     buf = SCDequeue(params->sfreeq);  /* SCDequeue might exit! */
  338.  
  339.     /*
  340.      * Get the scan data here!
  341.      */
  342.  
  343.     /*
  344.      * Chop the buffer up into scan line sized chunks
  345.      */
  346.     while (toread--) {
  347.         SCEnqueue(params->scanq, buf); /* SCEnqueue might exit! */
  348.         buf = (char *)buf + params->xbytes;
  349.     }
  350.     }
  351.  
  352.     exit(0);
  353. }
  354.  
  355. /*
  356.  * Document feeder functions.
  357.  *
  358.  * The template versions of these functions are simply stubs that
  359.  * inform the application that no document feeder is attached to the
  360.  * scanner.  If you are writing a driver for a scanner that supports a
  361.  * document feeder, these should be implemented appropriately.
  362.  */
  363.  
  364. /*
  365.  *  int
  366.  *  SetFeederFlags(SCANINFO *scan, SCFEEDERFLAGS flags)
  367.  *
  368.  *  Description:
  369.  *      Set document feeder flags.  flags should be set to either
  370.  *      SC_AUTOFEED or SC_PROGFEED, depending on whether the
  371.  *      application wants us to load the next document every time we
  372.  *      do a scan.
  373.  *
  374.  *      This function should only get called if scan->feederFlags have
  375.  *      both the SC_AUTOFEED and SC_PROGFEED bits set, indicating that
  376.  *      the application has to choose how it wants the feeder to act.
  377.  *
  378.  *  Parameters:
  379.  *      scan   scanner info
  380.  *      flags  either SC_AUTOFEED or SC_PROGFEED
  381.  *
  382.  *  Returns:
  383.  *      0 if successful, -1 if error
  384.  */
  385.  
  386. /*ARGSUSED*/
  387. int
  388. SetFeederFlags(SCANINFO *scan, SCFEEDERFLAGS flags)
  389. {
  390.     drverr = SCENOFEEDER;
  391.     return -1;
  392. }
  393.  
  394. /*
  395.  *  int
  396.  *  AdvanceFeeder(SCANINFO *scan)
  397.  *
  398.  *  Description:
  399.  *      Advance document feeder so that next document in the feeder
  400.  *      will be scanned from next time DoScan is called.  This should
  401.  *      only be called if we support SC_PROGFEED.  If we claimed
  402.  *      support for both SC_PROGFEED and SC_AUTOFEED, the application
  403.  *      should have called SetFeederFlags(SC_PROGFEED).
  404.  *
  405.  *  Parameters:
  406.  *      scan  scanner info.
  407.  *
  408.  *  Returns:
  409.  *      0 if successful, -1 if error
  410.  */
  411.  
  412. /*ARGSUSED*/
  413. int
  414. AdvanceFeeder(SCANINFO *scan)
  415. {
  416.     drverr = SCENOFEEDER;
  417.     return -1;
  418. }
  419.  
  420. /*
  421.  *  int
  422.  *  FeederReady(SCANINFO *scan)
  423.  *
  424.  *  Description:
  425.  *      Check whether the document feeder is ready; that is, it has
  426.  *      paper in it and will be used for scanning.
  427.  *
  428.  *  Parameters:
  429.  *      scan  scanner info
  430.  *
  431.  *  Returns:
  432.  *      0 if feeder is ready, -1 otherwise.
  433.  */
  434.  
  435. /*ARGSUSED*/
  436. int
  437. FeederReady(SCANINFO *scan)
  438. {
  439.     drverr = SCENOFEEDER;
  440.     return -1;
  441. }
  442.  
  443. /*
  444.  * The next two functions are used to implement the "-query" flag that
  445.  * each scanner driver must support.  scaninst uses this flag to get
  446.  * information about scanners on the system and scanner drivers that
  447.  * are installed to aid the user in setting up the
  448.  * /var/scan/scanners file.
  449.  */
  450.  
  451. /*
  452.  *  void
  453.  *  PrintID(FILE *fp)
  454.  *
  455.  *  Description:
  456.  *      Print a string to fp that describes the type of scanner that
  457.  *      this driver supports
  458.  *
  459.  *  Parameters:
  460.  *      fp  stream upon which to print scanner id string
  461.  */
  462.  
  463. void
  464. PrintID(FILE *fp)
  465. {
  466.     (void)fprintf(fp, "Scanner Template\n");   /* String describing scanner */
  467.     (void)fprintf(fp, "SCSI Serial Parallel\n");/* Device type; can be list */
  468. }
  469.  
  470. /*
  471.  *  void
  472.  *  FindScanners(FILE *fp)
  473.  *
  474.  *  Description:
  475.  *      Look for scanners that this driver can support.  For each such
  476.  *      driver, print the type of device, a space, and then the file
  477.  *      to open to access that scanner (usually a device special
  478.  *      file).
  479.  *
  480.  *      Type names are:
  481.  *          SCSI
  482.  *          Serial
  483.  *          Parallel
  484.  *          GPIB
  485.  *          EISA
  486.  *          Other
  487.  *
  488.  *  Parameters:
  489.  *      fp  stream upon which to print stuff
  490.  */
  491.  
  492. void
  493. FindScanners(FILE *fp)
  494. {
  495.     inventory_t *inv;
  496.     char device[100];
  497.     dsreq_t *dsp;
  498.     /* int because it must be word aligned. */
  499.     int inqbuf[(sizeof(INQDATA) + 3)/sizeof(int)];
  500.     INQDATA *inq = (INQDATA *)inqbuf;
  501.  
  502.     /*
  503.      * This example looks for SCSI scanners; do whatever is necesary
  504.      * to find other types of scanner here.
  505.      */
  506.     if (setinvent() < 0) {
  507.     return;
  508.     }
  509.  
  510.     while ((inv = getinvent()) != NULL) {
  511.     if (inv->inv_class == INV_SCSI && inv->inv_type == INV_SCANNER) {
  512.         (void)sprintf(device, "/dev/scsi/sc%dd%dl0", inv->inv_controller,
  513.               inv->inv_unit);
  514.         if ((dsp = dsopen(device, O_RDONLY)) == NULL) {
  515.         continue;
  516.         }
  517.  
  518.         if (inquiry12(dsp, (char *)inq, sizeof *inq, 0) == 0
  519.         && strncmp((char *)inq->vid, "vendorXX", 8) == 0 &&
  520.         strncmp((char *)inq->pid, "productXXXXXXXXX", 16) == 0) {
  521.         (void)fprintf(fp, "SCSI %s\n", device);
  522.         }
  523.         dsclose(dsp);
  524.     }
  525.     }
  526.  
  527.     endinvent();
  528. }
  529.  
  530. /*
  531.  *  int
  532.  *  InstallScanner(char *dev)
  533.  *
  534.  *  Description:
  535.  *      This function gets called to implement the "-install" option
  536.  *      of the driver.  The scanner installation tool wants to install
  537.  *      a scanner with us as the driver and dev as the device.
  538.  *
  539.  *      This function should verify that this is a reasonable thing to
  540.  *      do, and should also take steps to ensure that all users can
  541.  *      access the scanner.  This means that for SCSI scanners that
  542.  *      use the /dev/scsi interface, the following code should be
  543.  *      executed:
  544.  *
  545.  *           chmod(dev, 0666);
  546.  *
  547.  *      Suggestion: put the code that verfies that a device is valid
  548.  *      in the OpenScanner function, and then call OpenScanner from
  549.  *      within this function (InstallScanner).  If OpenScanner returns
  550.  *      NULL, print an error message and return -1.
  551.  *      
  552.  *      If for any reason a scanner with us as the driver and dev as
  553.  *      the device should NOT be installed, print an error message to
  554.  *      stdout, and return -1.  If it's OK to install the scanner,
  555.  *      return 0.
  556.  *
  557.  *      If we print something and return -1, then scaninst will
  558.  *      display the string.
  559.  *
  560.  *  Parameters:
  561.  *      dev   Device to use to install scanner
  562.  *
  563.  *  Returns:
  564.  *      0 if successful, -1 if error.
  565.  */
  566.  
  567. int
  568. InstallScanner(char *dev)
  569. {
  570.     (void)printf("The template driver doesn't support %s\n", dev);
  571.     return -1;
  572. }
  573.  
  574. /*
  575.  *  int
  576.  *  DeleteScanner(char *dev)
  577.  *
  578.  *  Description:
  579.  *      This function gives the scanner driver the opportunity to
  580.  *      deallocate any resources allocated during InstallScanner, and
  581.  *      to do any scanner-specific cleanup necessary for deleting a
  582.  *      scanner.
  583.  *
  584.  *      If an error occurs, print a message to stdout and return -1.
  585.  *      scaninst will display the message that gets printed and refuse
  586.  *      to delete the scanner.
  587.  *
  588.  *  Parameters:
  589.  *      dev   Device of scanner being deleted
  590.  *
  591.  *  Returns:
  592.  *      0 if successful, -1 if error.
  593.  */
  594.  
  595. /*ARGSUSED*/
  596. int
  597. DeleteScanner(char *dev)
  598. {
  599.     return 0;
  600. }
  601.  
  602. /*
  603.  *  void *
  604.  *  GetSaveOptions(SCANINFO *scan, int *nBytes)
  605.  *
  606.  *  Description:
  607.  *      This function should return to the main.c module a pointer to
  608.  *      some bytes representing our current settings that we got from
  609.  *      our scanner specific options program.  If we don't have a
  610.  *      scanner specific options program, we just set drverr and
  611.  *      return NULL.
  612.  *
  613.  *      The reason for doing this is so that the scanner application
  614.  *      can save some state for us, and at a later time give us the
  615.  *      same bytes back so that we can make our state match what it
  616.  *      was before.
  617.  *
  618.  *  Parameters:
  619.  *      scan    SCANINFO
  620.  *      nBytes  we fill this in with the number of bytes we're returning
  621.  *
  622.  *  Returns:
  623.  *      pointer to bytes containing scanner specific options settings
  624.  *      if successful, NULL if error.  drverr must be set to an
  625.  *      appropriate error code from <scanner.h> or <sys/errno.h> if an
  626.  *      error occurs.
  627.  */
  628.  
  629. void *
  630. GetSaveOptions(SCANINFO *scan, int *nBytes)
  631. {
  632.     drverr = SCENOSAVEOPT;
  633.     return NULL;
  634. }
  635.  
  636. /*
  637.  *  int
  638.  *  SetSaveOptions(SCANINFO *scan, void *options, int nBytes)
  639.  *
  640.  *  Description:
  641.  *      In this function, the scanner application is restoring state
  642.  *      that it previously saved after calling GetSaveOptions.  We
  643.  *      should reset our state to reflect the options passed to us.
  644.  *
  645.  *      These are scanner specific settings that were set by our
  646.  *      scanner specific options program; we don't need to worry about
  647.  *      things like resolution and scanning area and data type that
  648.  *      are a part of the standard scanning protocol here.
  649.  *
  650.  *  Parameters:
  651.  *      scan     SCANINFO
  652.  *      options  the saved settings
  653.  *      nBytes   number of bytes pointed to by options
  654.  *
  655.  *  Returns:
  656.  *      0 if successful, -1 if error.  drverr must be set to an
  657.  *      appropriate error code from <scanner.h> or <sys/errno.h> if an
  658.  *      error occurs.
  659.  */
  660.  
  661. int
  662. SetSaveOptions(SCANINFO *scan, void *options, int nBytes)
  663. {
  664.     drverr = SCENOSAVEOPT;
  665.     return -1;
  666. }
  667.